<?php

namespace common\components;

use yii\base\ErrorException;
use yii\base\Exception;
use \yii\web\UploadedFile;
use Yii;

/**
 * @todo 封装原图的url path
 * 对上传操作进行封装
 *
 * @author qixiaopeng <qixiaopeng@ledoing.cn>
 */
class Upload extends \yii\base\Component
{

    const TYPE_IMAGE = 'image';
    const TYPE_AUDIO = 'audio';
    const TYPE_VIDEO = 'video';

    /**
     * @var UploadedFile
     */
    //生成缩略图的尺寸
    public $coverName = [
        'teamWorkCover' => [
            '0' => [210, 360] // 宽 高
        ],
        'userWorkCover' => [
            '0' => [210, 360]
        ],
        'userHead' => [
            '0' => [32, 32]
        ]
    ];

    /**
     * @var ImageMagic
     */
    public $imaGic;

    /**
     * @var 上传文件类型 image video audio
     */
    public $uploadType;

    /**
     * @var 允许上传的文件类型
     */
    public $allowedType;

    /**
     * @var 上传文件的路径
     */
    public $path;

    /**
     * @var 宽
     */
    public $width;

    /**
     * @var 高
     */
    public $height;

    /**
     * @var 文件大小
     */
    public $size;

    /**
     * @var 文件属性名
     */
    public $id;

    /**
     * @var 生成缩略的图的标识
     */
    public $category;

    /**
     * @var 文件
     */
    public $file;

    /**
     * @var 文件数组
     */
    public $fileArray;

    /**
     * @var 文件短连接名称
     */
    public $shortFileName;

    public function __construct(array $options)
    {
        if (empty($this->imaGic)) {
            $this->imaGic = new ImageMagic();
        }
        if (empty($options)) {
            return;
        }
        foreach ($options as $key => $val) {
            $this->$key = $val;
        }
    }

    public function fileInit()
    {
        $this->file = UploadedFile::getInstanceByName($this->id);
    }

    public function validator()
    {
        $data['files'] = [];
        $imageType = array_filter(explode(',', $this->allowedType));
        if (!in_array($this->file->getExtension(), $imageType)) {
            $data['files'][] = [
                'error' => '文件格式不正确',
                'name' => $this->file->getBaseName() . '.' . $this->file->getExtension(),
                'type' => $this->file->type,
                'size' => $this->file->size
            ];
            return $data;
        }
        if (($this->file->size > $this->size) && $this->size > 0) {
            $data['files'][] = [
                'error' => '文件太大',
                'name' => $this->file->getBaseName() . '.' . $this->file->getExtension(),
                'type' => $this->file->type,
                'size' => $this->file->size
            ];
            return $data;
        }
        return $data;
    }

    /* public function validatorImage(){
      $imageArray= $this->getImageGeometry($this->fileArray['url']);

      } */

    public function process()
    {
        $files = [];
        switch ($this->uploadType) {
            case self::TYPE_VIDEO:
                $files = [$this->fileArray['shortName'] . '.' . $this->fileArray['extension'] => $this->fileArray['absolutePath']];
                break;
            case self::TYPE_IMAGE:
                if (!empty($this->width) && !empty($this->height)) {
                    $error = $this->validatorImage();
                    if (!empty($error['files'])) {
                        return $error;
                    }
                }
                $error = $this->processImage();
                if (!empty($error['files'])) {
                    return $error;
                }
                $files = $this->fileArray['thumbImage'];
                break;
            case self::TYPE_AUDIO:
                $files = [$this->fileArray['shortName'] . '.' . $this->fileArray['extension'] => $this->fileArray['absolutePath']];
                break;
        }
        $error = $this->sendToFtp($files);
        if (!empty($error['files'])) {
            return $error;
        }
        $error = $this->removeFile($files);
        if (!empty($error['files'])) {
            return $error;
        }
        $data['files'] = [];
        return $data;
    }

    public function processImage()
    {
        $data['files'] = [];
        if (!empty($this->coverName[$this->category])) {
            $result = $this->imaGic->createThumb($this->fileArray, $this->coverName[$this->category]);
            if (empty($result)) {
                $data['files'][] = [
                    'error' => '参数传递有误'
                ];
                return $data;
            }
           // print_r($result);exit;
            $result[$this->fileArray['shortName'] . '.' . $this->fileArray['extension']] = $this->fileArray['absolutePath'];
            $this->fileArray['thumbImage'] = $result;
        }else{
            $this->fileArray['thumbImage'] = [$this->fileArray['shortName'] . '.' . $this->fileArray['extension'] => $this->fileArray['absolutePath']];
        }

        return $data;
    }

    /**
     * 1. 生成路径
     * 2. 生成文件名
     * 3. 移动文件
     */
    public function createLocalFile($_path = '')
    {
        $errorData = $this->validator();
        if (!empty($errorData['files'])) {
            return $errorData;
        }
        $this->createLocalPath($_path);
        $savePath = $this->fileArray['basePath'] . $this->fileArray['path'];
        $this->createFileName();
        $saveFileName = $this->fileArray['shortName'] . '.' . $this->fileArray['extension'];
        $this->file->saveAs($savePath . DIRECTORY_SEPARATOR . $saveFileName);
        $this->fileArray['absolutePath'] = $savePath . DIRECTORY_SEPARATOR . $saveFileName;
        $data['files'] = [];
        return $data;
    }

    public function createLocalPath($_path = '')
    {
        if (!empty($_path)) {
            $basePath = $_path;
        } else {
            $basePath = \Yii::$app->getBasePath() . DIRECTORY_SEPARATOR . 'web' . DIRECTORY_SEPARATOR . 'uploads'.DIRECTORY_SEPARATOR;
        }
        $path = trim($this->path, '\/');
        if (!empty($path)) {
            $path =   $path . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d');
        } else {
            $path =   date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d');
        }

        if (!file_exists($basePath . $path)) {
            mkdir($basePath . $path, 0777, true);
        }
        $this->fileArray['basePath'] = $basePath;
        $this->fileArray['path'] = $path;
        return $this->fileArray;
    }

    public function createFileName()
    {
        $shortName = $this->shortUrl(md5($this->file->getBaseName() . microtime(true)));
        $extension = $this->file->getExtension();
        $this->fileArray['shortName'] = $shortName[0];
        $this->fileArray['extension'] = $extension;
        return $this->fileArray;
    }

    /**
     * 获取图片的宽 高
     * @return array
     */
    public function getImageGeometry()
    {
        return $this->imaGic->getImageGeometry($this->fileArray['absolutePath']);
    }

    // c
    public function validatorImage()
    {
        $width = explode(',', $this->width);
        //print_r($width);exit;
        $height = explode(',', $this->height);
        $imageArray = $this->getImageGeometry();
        //print_r($imageArray);exit;
        $data['files'] = [];
        if ($width[1] != 0) {
            if ($imageArray['width'] > $width[1]) {
                $data['files'][] = [
                    'error' => '图片太宽,宽的尺寸：', $width[0] . '-' . $width[1],
                    'name' => $this->fileArray['shortName'] . '.' . $this->fileArray['extension'],
                    'type' => $this->fileArray['extension']
                ];
                $result = $this->removeFile($this->fileArray['url']);
                if (!$result) {
                    //throw new Exception("删除文件失败, 宽的尺寸：" . $width[0] . '-' . $width[1]);
                    $data['files'][] = [
                        'error' => '删除文件失败'
                    ];
                    return $data;
                }
                return $data;
            }
        }
        if ($height[1] != 0) {
            if ($imageArray['height'] > $height[1]) {
                $data['files'][] = [
                    'error' => '图片太高,高的尺寸为:' . $height[0] . '-' . $height[1],
                    'name' => $this->fileArray['shortName'] . '.' . $this->fileArray['extension'],
                    'type' => $this->fileArray['extension']
                ];
                $result = $this->removeFile($this->fileArray['url']);
                if (!$result) {
                    $data['files'][] = [
                        'error' => '删除文件失败'
                    ];
                    return $data;
                }
                return $data;
            }
        }
        return $data;
    }

    public function createThumb($file = [], $thumb = [])
    {
        return $this->imaGic->createThumb($file, $thumb);
    }

    /**
     * 短连接生成
     * @param $filename
     * @return array
     */
    function shortUrl($filename)
    {
        $key = 'heiguang';
        $base32 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        // 利用md5算法方式生成hash值
        $hex = hash('md5', $filename . $key);
        $hexLen = strlen($hex);
        $subHexLen = $hexLen / 8;

        $output = array();
        for ($i = 0; $i < $subHexLen; $i++) {
            // 将这32位分成四份，每一份8个字符，将其视作16进制串与0x3fffffff(30位1)与操作
            $subHex = substr($hex, $i * 8, 8);
            $idx = 0x3FFFFFFF & (1 * ('0x' . $subHex));

            // 这30位分成6段, 每5个一组，算出其整数值，然后映射到我们准备的62个字符
            $out = '';
            for ($j = 0; $j < 6; $j++) {
                $val = 0x0000003D & $idx;
                $out .= $base32[$val];
                $idx = $idx >> 5;
            }
            $output[$i] = $out;
        }

        return $output;
    }
    public function createUploadFileUrl(){
        return DIRECTORY_SEPARATOR . $this->fileArray['path'] . DIRECTORY_SEPARATOR . $this->fileArray['shortName'] . '.' . $this->fileArray['extension'];
    }
    /**
     * @param array $files
     * @return mixed
     */
    public function sendToFtp(array $files)
    {
        $data['files'] = [];
        $resutlt = Yii::$app->ftp->isdir($this->fileArray['path']);
        if (!$resutlt) {
            $result = Yii::$app->ftp->mkdir($this->fileArray['path'], true);
            if (!$result) {
                $data['files'][] = [
                    'error' => '创建目录' . $this->fileArray['path'] . '失败',
                ];
                return $data;
            }
        }
        $result = Yii::$app->ftp->chdir($this->fileArray['path']);
        //var_dump($result);exit;
        if (!$result) {
            $data['files'][] = [
                'error' => '切换目录' . $this->fileArray['path'] . '失败',
            ];
            return $data;
        }
        $result = Yii::$app->ftp->puts($files);
        //var_dump($files);exit;
        if (!$result) {
            $data['files'][] = [
                'error' => '远程推送文件失败',
            ];
            return $data;
        }
        return $data;
    }

    /**
     * 删除本地图片
     * @param $path
     * @return bool
     */
    public function removeFile($path)
    {
        if (is_string($path)) {
            $boole = unlink($path);
            if (!$boole) {
                return false;
            }
            return true;
        }
        $result = false;
        if (is_array($path)) {
            foreach ($path as $val) {
                $result = unlink($val);
            }
        }
        return $result;
    }

}
